home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / x11 / video.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-07  |  22.1 KB  |  861 lines

  1. #include <X11/Xlib.h> 
  2. #include <X11/Xutil.h>
  3. #include <X11/keysym.h>
  4.  
  5. #ifndef NO_XSHM
  6. #include <sys/ipc.h>
  7. #include <sys/shm.h>
  8. #include <X11/extensions/XShm.h>
  9. #include <signal.h>
  10. #endif
  11.  
  12.  
  13. #include <string.h>
  14. #ifdef _AIX
  15. #include <strings.h>
  16. //#include <X11/AIX.h>
  17. //#include <X11/extensions/Xdfb.h>
  18. #endif
  19.  
  20. #include "filter.hpp"
  21. #include "globals.hpp"
  22. #include "system.h"
  23. #include "video.hpp"
  24. #include "dos.h"
  25. #include "xinclude.h"
  26. #include "macs.hpp"
  27. #include "bitmap.h"
  28. #include "image.hpp"
  29. #include "jmalloc.hpp"
  30.  
  31. unsigned char current_background;
  32. extern unsigned int xres,yres;
  33. extern palette *lastl;
  34. int X_xoff,Y_yoff,vmode;
  35. image *screen;
  36. char display_name[120];
  37.  
  38. Window root;
  39. Display *display;
  40. int screen_num;
  41. Screen *screen_ptr;
  42. unsigned border_width,depth;
  43. Colormap XCMap;
  44. Window mainwin;
  45. GC gc;
  46. XFontStruct *font_info;
  47. XVisualInfo *my_visual;
  48. Visual *X_visual;
  49.  
  50. int pixel_scale=1;
  51.  
  52. uchar last_load_palette[256*4];  // store word alligned for faster access
  53.  
  54. static int fullscreen=0;
  55. static int dfb=0;
  56.  
  57.  
  58. // ========================================================================
  59. // makes a null cursor
  60. // ========================================================================
  61.  
  62. static Cursor CreateNullCursor(Display *display, Window root)
  63. {
  64.     Pixmap cursormask; 
  65.     XGCValues xgc;
  66.     GC gc;
  67.     XColor dummycolour;
  68.     Cursor cursor;
  69.  
  70.     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
  71.     xgc.function = GXclear;
  72.     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
  73.     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
  74.     dummycolour.pixel = 0;
  75.     dummycolour.red = 0;
  76.     dummycolour.flags = 04;
  77.     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
  78.           &dummycolour,&dummycolour, 0,0);
  79.     XFreePixmap(display,cursormask);
  80.     XFreeGC(display,gc);
  81.     return cursor;
  82. }
  83.  
  84.  
  85.  
  86. #ifndef NO_XSHM
  87. // ************** SHM Vars *******************
  88. int shm_base,shm_error_base,shm_finish_event,doShm=0;
  89.  
  90.  
  91. struct event_node
  92. {
  93.   XEvent report;  
  94.   event_node *next;  
  95. } ;
  96.  
  97.  
  98. void wait_shm_finish()
  99. {
  100.   event_node *en,*first=NULL;
  101.   while (1)
  102.   { 
  103.     en=(event_node *)jmalloc(sizeof(event_node),"shm_wait : event");
  104.     XNextEvent(display, &en->report);
  105.  
  106.     // if this is the finishing event, put all the stored events back
  107.     // on the que
  108. #ifndef NO_XSHM
  109.     if (en->report.type==shm_base+ShmCompletion)
  110.     {
  111.       jfree(en);
  112.       
  113.       while (first)
  114.       {
  115.     XPutBackEvent(display,&first->report);
  116.     en=first;
  117.     first=first->next;
  118.     jfree(en);    
  119.       }
  120.       return ;      
  121.     } else // put the event on the que to be puback
  122. #endif
  123.     {
  124.       en->next=first;     // put the back in reverse order
  125.       first=en;
  126.     }    
  127.   }
  128. }
  129.  
  130.     
  131. #endif
  132.  
  133.  
  134. int get_vmode()
  135. { return vmode; }
  136.  
  137. void getGC(Window win, GC *gc, XFontStruct *font_info)
  138. {
  139.   XGCValues values;
  140.   *gc=XCreateGC(display,win,0,&values);
  141.   XSetFont(display, *gc, font_info->fid);
  142.   XSetForeground(display, *gc, BlackPixel(display,screen_num));
  143.   XSetLineAttributes(display, *gc, 1, LineSolid, CapRound, JoinRound);
  144. }
  145.  
  146.  
  147. class XImage_Info             // stored in the extended desciptor
  148. {
  149. public :
  150.   
  151. #ifndef NO_XSHM
  152.   XShmSegmentInfo X_shminfo;    
  153. #endif
  154.   XImage *XImg;
  155. } ;
  156.  
  157.  
  158. void image::make_page(short width, short height, unsigned char *page_buffer)
  159. {
  160.   XImage_Info *xi;  
  161.   if (special && !special->static_mem)
  162.   {
  163.     xi=new XImage_Info;
  164.     special->extended_descriptor=(void *)xi;    
  165. #ifndef NO_XSHM
  166.     if (doShm)
  167.     {
  168.       width=(width+3)&(0xffffffff-3);
  169.       // create the image
  170.       xi->XImg = XShmCreateImage(display,
  171.                  X_visual,
  172.                  my_visual->depth,
  173.                  ZPixmap,
  174.                  0,
  175.                  &xi->X_shminfo,
  176.                  width*pixel_scale,
  177.                  height*pixel_scale);
  178.  
  179.       w = width = xi->XImg->bytes_per_line / pixel_scale;
  180.  
  181.       // create the shared memory segment
  182.       xi->X_shminfo.shmid = shmget (IPC_PRIVATE,
  183.           width*height*pixel_scale*pixel_scale, IPC_CREAT | 0777);
  184.       ERROR(xi->X_shminfo.shmid>=0,"shmget() failed, go figure");
  185.  
  186.       xi->X_shminfo.readOnly=False;
  187.  
  188.       // attach to the shared memory segment to us
  189.       xi->XImg->data = xi->X_shminfo.shmaddr =
  190.         (char *) shmat(xi->X_shminfo.shmid, 0, 0);
  191.       ERROR(xi->XImg->data,"shmat() failed, go figure");
  192.  
  193.       // get the X server to attach to it to the X server
  194.       ERROR(XShmAttach(display, &xi->X_shminfo),"XShmAttach() failed, go figure");
  195.       XSync(display,False); // make sure segment gets attached
  196.       ERROR(shmctl(xi->X_shminfo.shmid,IPC_RMID,NULL)==0,"shmctl failed, why?"); 
  197.  
  198.       if (pixel_scale == 1)
  199.         data=(unsigned char *) (xi->XImg->data);
  200.       else
  201.         data=(unsigned char *) jmalloc(width*height, "unscaled image");
  202.     } else 
  203. #endif
  204.     {
  205.       width=(width+3)&(0xffffffff-3);        
  206.       if (!page_buffer)
  207.         page_buffer=
  208.             (unsigned char *)jmalloc(width*height*pixel_scale*pixel_scale,
  209.             "image::data");
  210.       
  211.       xi->XImg = XCreateImage(    display,
  212.                     X_visual,
  213.                     my_visual->depth,
  214.                     ZPixmap,
  215.                     0,
  216.                     (char *)page_buffer,
  217.                     width*pixel_scale,
  218.                     height*pixel_scale,
  219.                     32,
  220.                     0 );
  221.       ERROR(xi->XImg,"XCreateImage failed");
  222.  
  223.       w = width = xi->XImg->bytes_per_line / pixel_scale;
  224.  
  225.       if (pixel_scale == 1)
  226.           data=(unsigned char *) (xi->XImg->data);
  227.         else
  228.         data=(unsigned char *) jmalloc(width*height, "unscaled image");
  229.     }    
  230.   }
  231.   else 
  232.   {
  233.     if (!page_buffer)
  234.       data=(unsigned char *)jmalloc(width*height,"image::data");
  235.     else data=page_buffer;
  236.   }
  237.  
  238.   if (special)
  239.     special->resize(width,height);
  240.  
  241. }
  242.  
  243. void image::delete_page()
  244.   XImage_Info *xi;  
  245.   if (special && !special->static_mem && special->extended_descriptor)
  246.   {    
  247.     xi=(XImage_Info *)special->extended_descriptor;    
  248. #ifndef NO_XSHM
  249.     if (doShm)
  250.     {    
  251.       XFlush(display);
  252.       XSync(display,False);  // maker sure anything with this image is drawn!
  253.  
  254.       // Dettach the memory from the server
  255.       ERROR(XShmDetach(display, &xi->X_shminfo),"XShmDetach() failed, go figure");
  256.  
  257.       XSync(display,False);  // maker sure server detached
  258.  
  259.       // detach the memory from us, it will be deleted!
  260.       ERROR(shmdt(xi->X_shminfo.shmaddr)>=0,"shmdt failed, oops");
  261.  
  262.       xi->XImg->data=NULL;  // tell X not to try to free the memory, cause we already did.
  263.  
  264.       XDestroyImage(xi->XImg);    
  265.  
  266.       if (pixel_scale > 1)
  267.         jfree(data);
  268.  
  269.     } else
  270. #endif
  271.     {
  272.       if (!special->static_mem)
  273.         jfree(xi->XImg->data);
  274.       xi->XImg->data=NULL;                  // make sure X doesn't try to free static memory
  275.       XDestroyImage(xi->XImg);    
  276.  
  277.       if (pixel_scale > 1)
  278.         jfree(data);
  279.     }
  280.     delete xi;
  281.   }
  282.   else if (!special)
  283.     jfree(data);      
  284. }
  285.  
  286.  
  287. #ifndef NO_XSHM
  288. #ifdef __sgi
  289. void clean_shm(...)
  290. #else
  291. void clean_shm(int why)      // on exit, delete all images, so shm get de-allocated.
  292. #endif
  293. {
  294.   while (image_list.first())
  295.   {
  296.     image *i=(image *)image_list.first();
  297.     delete i;
  298.   }
  299. }
  300. #endif
  301.  
  302. void set_mode(int mode, int argc, char **argv)
  303. {
  304.   unsigned char *page;
  305.   vmode=mode;
  306.   XVisualInfo vis_info;
  307.   int items,i;
  308.   XEvent report;
  309.   XWMHints *wm_hints;
  310.   XClassHint *class_hints;
  311.   XTextProperty winName,iconName;
  312.   XSizeHints *size_hints;
  313.   char *win_name=argv[0],        // name the window and the icon the executable name
  314.        *icon_name=argv[0];
  315.   Pixmap icon_pixmap;
  316.   
  317.   // get the default display name from the enviroment variable DISPLAY
  318.   char *ds_name=getenv("DISPLAY");
  319.   if (!ds_name) ds_name="unix:0.0";
  320.   strcpy(display_name,ds_name); 
  321.  
  322.   int suppress_shm=0;
  323.  
  324.   // check for command line display name
  325.   for (i=1;i<argc;i++)
  326.   {
  327.     if (!strcasecmp(argv[i],"-display") || !strcasecmp(argv[i],"-disp"))
  328.     {
  329.       i++;      
  330.       strcpy(display_name,argv[i]);  
  331.     }    
  332.     else if (!strcasecmp(argv[i],"-noshm"))
  333.       suppress_shm=1;
  334.     else if (!strcasecmp(argv[i],"-pixel_scale"))
  335.       pixel_scale=atoi(argv[i+1]);
  336.     else if (!strcasecmp(argv[i],"-fullscreen"))
  337.         {
  338.       fullscreen=1;
  339.             pixel_scale=2;
  340.         }
  341.     else if (!strcasecmp(argv[i],"-dfb"))
  342.         {
  343.       fullscreen=1;
  344.             pixel_scale=2;
  345.             dfb = 1;
  346.         }
  347.   }
  348.     
  349.   display=XOpenDisplay(display_name);  
  350.   if (!display)
  351.   {
  352.     printf("Cound not connect to X server named '%s'\n",display_name);
  353.     exit(1);
  354.   }
  355.  
  356. #ifndef NO_XSHM
  357.   // check for the MITSHM extension
  358.   int major_op;
  359.   
  360.   if (suppress_shm)
  361.     doShm=0;
  362.   else
  363.     doShm = XQueryExtension(display,"MIT-SHM",&major_op,&shm_base,&shm_error_base);
  364.  
  365.   // make sure it's a local connection
  366.   if (doShm)
  367.   {    
  368.     char *d = display_name;
  369.     while (*d && (*d != ':')) d++;
  370.     if (*d) *d = 0;
  371.     if (strcasecmp(display_name, "unix") && display_name[0]!=0) 
  372.       doShm = 0;   
  373.   }
  374.  
  375.   if (doShm)
  376.   {
  377.     printf("Using MITSHM extension!\n");
  378.     int sigs[29]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,
  379.         SIGABRT,SIGIOT,SIGBUS,SIGFPE,SIGKILL,
  380.         SIGUSR1,SIGSEGV,SIGUSR2,SIGPIPE,SIGALRM,
  381.                 SIGTERM,SIGCHLD,SIGCONT,SIGSTOP,
  382.         SIGTSTP,SIGTTIN,SIGTTOU,SIGIO,
  383.         SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGPROF,
  384.         SIGWINCH};
  385.  
  386.     for (int i=0;i<29;i++)
  387.       signal(sigs[i],clean_shm);
  388.   }
  389. #endif
  390.   depth=8;
  391.   screen_num = DefaultScreen(display);
  392.   screen_ptr = DefaultScreenOfDisplay(display);
  393.   ERROR(XGetGeometry(display,RootWindow(display,screen_num), &root,
  394.     &X_xoff,&Y_yoff,&xres,&yres,&border_width,&depth),
  395.     "can't get root window attributes");
  396.  
  397.   {
  398.     vis_info.c_class=PseudoColor;       
  399.     vis_info.depth=8;
  400.     my_visual=XGetVisualInfo(display,VisualClassMask | VisualDepthMask, &vis_info,&items);
  401.  
  402.     if (items>0)
  403.     {
  404.       int rc;
  405.  
  406.       X_visual=my_visual->visual;
  407.       vmode=XWINDOWS_256;
  408.  
  409.       rc=XMatchVisualInfo(display, screen_num, 8, PseudoColor, &vis_info);
  410.       ERROR(rc, "What the hell? Non-8 bit Psuedo color..\n");
  411.       X_visual = my_visual->visual = vis_info.visual;
  412.       //    ERROR(my_visual->depth==8,"What the hell? Non-8 bit Psuedo color..\n");
  413.       printf("Using 8 bit Psuedo color\n");
  414.     }
  415.     else
  416.     { 
  417.       printf("X windows screen type not supported\n");
  418.       exit(0); 
  419.     }
  420.   }
  421.  
  422.   xres=320; yres=200;
  423.   for (i=1;i<argc;i++)
  424.   { if (!strcmp(argv[i],"-size"))
  425.     { i++; if (!sscanf(argv[i],"%d",&xres)) xres=320;
  426.       i++; if (!sscanf(argv[i],"%d",&yres)) yres=200;
  427.     }
  428.   }
  429.  
  430.  
  431.   Colormap tmpcmap;
  432.   
  433.   tmpcmap = XCreateColormap(display, XRootWindow(display,
  434.                         my_visual->screen), X_visual, AllocNone);
  435.  
  436.   int attribmask = CWColormap | CWBorderPixel;
  437.   XSetWindowAttributes attribs;
  438.   attribs.border_pixel = 0;
  439.   attribs.colormap = tmpcmap;
  440.   
  441.   mainwin=XCreateWindow(display,
  442.             XRootWindow(display,my_visual->screen),
  443.             0,0,fullscreen ? 640 : (xres*pixel_scale), fullscreen ? 480 : (yres*pixel_scale),
  444.             0,
  445.             my_visual->depth,
  446.             InputOutput,
  447.             X_visual,
  448.             attribmask,
  449.             &attribs);
  450.   xres--; yres--;
  451.  
  452.  
  453.   icon_pixmap=XCreateBitmapFromData(display,mainwin,bitmap_bits,
  454.     bitmap_width, bitmap_height);
  455.   ERROR((size_hints=XAllocSizeHints()),"memory allocation error");
  456.   ERROR((wm_hints=XAllocWMHints()),"memory allocation error");
  457.   ERROR((class_hints=XAllocClassHint()),"memory allocation error");
  458.  
  459.   int lock=0;
  460.   for (i=1;i<argc;i++)
  461.     if (!strcmp(argv[i],"-lock_size"))
  462.      lock=1;
  463.  
  464. /*
  465.   if (lock)
  466.   {
  467.     size_hints->flags=PPosition | PSize | PMinSize | PMaxSize;
  468.     size_hints->min_width  = (xres+1)*pixel_scale;
  469.     size_hints->min_height = (yres+1)*pixel_scale;
  470.     size_hints->max_width  = (xres+1)*pixel_scale;
  471.     size_hints->max_height = (yres+1)*pixel_scale;
  472.   }
  473.   else
  474.   {
  475. */
  476. //    size_hints->flags=PPosition | PSize | PMinSize;
  477.     size_hints->flags=PMinSize | PMaxSize;
  478.     size_hints->min_width  = (xres+1)*pixel_scale;
  479.     size_hints->min_height = (yres+1)*pixel_scale;
  480.     size_hints->max_width  = (xres+1)*pixel_scale;
  481.     size_hints->max_height = (yres+1)*pixel_scale;
  482. // }
  483.  
  484.  
  485.   ERROR(XStringListToTextProperty(&win_name,1,&winName),"alloc failed");
  486.   ERROR(XStringListToTextProperty(&icon_name,1,&iconName),"alloc fialed");
  487.   wm_hints->initial_state=NormalState;  // not iconified at first
  488.   wm_hints->input=1;                  // needs keyboard input
  489.   wm_hints->icon_pixmap=icon_pixmap;
  490.   wm_hints->flags=StateHint | IconPixmapHint | InputHint;
  491.   class_hints->res_name=argv[0];
  492.   class_hints->res_class="(C) 1995 Crack dot Com, Jonathan Clark";
  493.   XSetWMProperties(display,mainwin,&winName,&iconName,argv,argc,size_hints,
  494.     wm_hints,class_hints);
  495.   XSelectInput(display,mainwin,ExposureMask|KeyPressMask|ButtonPressMask|
  496.     (fullscreen ? 0 : StructureNotifyMask));
  497.   ERROR(font_info=XLoadQueryFont(display,"9x15"),"cannot open 9x15");
  498.   getGC(mainwin,&gc,font_info);
  499.  
  500. /* try to determine what type of monitor we are using */
  501.  
  502.  
  503.   // detect which type of screen the X client will run on...
  504.   // if they requested 24 bit mode, check for that type of display
  505.  
  506.  
  507.  
  508.   XSetBackground(display,gc,BlackPixel(display,screen_num));
  509.  
  510.   XMapWindow(display,mainwin);
  511.   do
  512.   { XNextEvent(display, &report);
  513.   } while (report.type!= Expose);     // wait for our window to pop up
  514.  
  515.     if (fullscreen)
  516.     {
  517.  
  518.         int src_x, src_y, x, y;
  519.         unsigned nchildren, width, height, border_width, depth;
  520.         Window root, child, rootwin, parentwin, currentwin, *children;
  521.         XWindowAttributes attribs;
  522.  
  523.         XGetGeometry(display, mainwin, &root, &src_x, &src_y, &width, &height, &border_width, &depth);
  524.         XFillRectangle(display, mainwin, gc, 0, 0, width, height);
  525.         XTranslateCoordinates (display, mainwin, root, src_x, src_y, &x, &y, &child);
  526.         parentwin = mainwin;
  527.         do
  528.         {
  529.             currentwin = parentwin;
  530.             XQueryTree(display, currentwin, &rootwin, &parentwin, &children, &nchildren);
  531.             XFree(children);
  532.         } while (rootwin != parentwin);
  533.         XGetWindowAttributes(display, currentwin, &attribs);
  534.         XMoveWindow(display, mainwin, -((attribs.width - width)/2), -(attribs.height
  535.             - height - ((attribs.width - width)/2)));
  536.  
  537. #ifdef _AIX
  538. //        XDAEChangeDisplayResolution(display, mainwin, Resolution640X480X60Hz);
  539. #endif
  540.  
  541.     }
  542.  
  543.   XDefineCursor(display,mainwin, CreateNullCursor(display,mainwin));
  544.  
  545.   screen=new image(xres+1,yres+1,NULL,2);  
  546.  
  547.   XCMap=XCreateColormap(display,mainwin,X_visual,AllocAll);  
  548.   screen->clear();
  549.   update_dirty(screen);
  550.  
  551.   for (i=1;i<argc;i++)
  552.   { if (!strcmp(argv[i],"-grab_pointer"))
  553.     {
  554.       i++;
  555.       int sec;
  556.       if (i<argc && sscanf(argv[i],"%d",&sec))
  557.       { printf("-grab_pointer : delaying for %d seconds\n",sec);
  558.     sleep(sec);
  559.       }
  560.       if (XGrabPointer(display,mainwin,True,
  561.                PointerMotionMask|ButtonMotionMask|
  562.                Button1MotionMask|
  563.                Button2MotionMask|
  564.                Button3MotionMask|
  565.                Button4MotionMask|
  566.                Button5MotionMask,
  567.                GrabModeAsync,
  568.                GrabModeAsync,
  569.                mainwin,
  570.                None,
  571.                CurrentTime)==GrabSuccess)
  572.         printf("Pointer grab in effect!\n");
  573.       else
  574.         printf("Unable to grab pointer  :(\n");
  575.     }
  576.   }
  577.     
  578. }
  579.  
  580. void close_graphics()
  581. {
  582.   if (lastl) delete lastl; lastl=NULL;
  583.   delete screen;
  584. #ifdef _AIX
  585. //    XDAEChangeDisplayResolution(display, mainwin, DefaultResolution);
  586. #endif
  587.   XUnloadFont(display,font_info->fid);
  588.   XFreeGC(display,gc);
  589.   XFree((char *)my_visual);
  590.   XCloseDisplay(display);
  591. }
  592.  
  593. void scale_image(image *im, int src_x, int src_y, int src_w, int src_h)
  594. {
  595.  
  596.   uchar *src;
  597.   ushort *dst;
  598.   ushort pixel;
  599.   int dx;
  600.   int y;
  601.   int next_dst_line;
  602.   int w;
  603.   XImage_Info *xi=(XImage_Info *)im->special->extended_descriptor;
  604.  
  605.   if (pixel_scale == 2)
  606.   {
  607.       src=im->scan_line(src_y)+src_x;
  608.       dst=(ushort *) (xi->XImg->data+src_y*xi->XImg->bytes_per_line*2+src_x*2);
  609.       next_dst_line = xi->XImg->bytes_per_line/2;
  610.       w = im->width();
  611.  
  612.       for (y=src_h;y;y--)
  613.       {
  614.         for (dx=0;dx<src_w;dx++)
  615.         {
  616.           pixel = *(src+dx);
  617.           pixel |= pixel<<8;
  618.           *(dst+dx) = pixel;
  619.           *(dst+dx+next_dst_line) = pixel;
  620.         }
  621.         src += w;
  622.         dst += xi->XImg->bytes_per_line;
  623.       }
  624.  
  625.   }
  626.  
  627. }
  628.  
  629. void copy_24part(uchar *Xdata, image *im, int x1, int y1, int x2, int y2)
  630. {
  631.   uchar *src=im->scan_line(y1)+x1;
  632.   ushort *dst=(ushort *)Xdata+(y1*2)*im->width()+x1;
  633.  
  634.   int src_add=im->width()-(x2-x1+1);
  635.  
  636.   int x,y,w=(x2-x1+1)*2;
  637.   ushort v;
  638.   for (y=y1;y<=y2;y++)
  639.   {
  640.     for (x=x1;x<=x2;x++)
  641.     {
  642.       v=*(src++);
  643.       *(dst++)=(v|(v<<8));
  644.     }    
  645.     dst=(ushort *) ((uchar *)dst+src_add*2);
  646.     memcpy(dst,(uchar *)dst-im->width()*2,w);
  647.     dst=(ushort *)((uchar *)dst+im->width()*2);
  648.  
  649.     src+=src_add;
  650.   }
  651. }
  652.  
  653.  
  654.  
  655. void put_part_image(Window win, image *im, int x, int y, int x1, int y1, int x2, int y2)
  656. {
  657.   CHECK(im->special);
  658.   XImage_Info *xi=(XImage_Info *)im->special->extended_descriptor;
  659.  
  660. //    fprintf(stderr, "(%dx%d) ppi: d=%d,%d s=%d,%d->%d,%d\n", xres, yres, x, y, x1, y1, x2, y2);
  661.  
  662.   if (pixel_scale>1)
  663.     scale_image(im,x1,y1,x2-x1+1,y2-y1+1);
  664.  
  665. #ifndef NO_XSHM
  666.   if (doShm)
  667.   {    
  668.     XEvent ev;
  669.     XSync(display,False);
  670.     if (XCheckTypedEvent(display, ConfigureNotify,&ev)==False)
  671.     {
  672.       XShmPutImage(display,win,gc,xi->XImg,x1*pixel_scale,y1*pixel_scale,
  673.         x*pixel_scale,y*pixel_scale+(fullscreen?40:0),(x2-x1+1)*pixel_scale,
  674.         (y2-y1+1)*pixel_scale,True);
  675.       // wait for the Put to finish
  676.       wait_shm_finish();
  677.     } else     // screen size changed,  better wait till this event is handled cause put might be invalid
  678.       XPutBackEvent(display,&ev);
  679.  
  680.   }  
  681.   else  
  682. #endif
  683.     XPutImage(display,win,gc,xi->XImg,x1*pixel_scale,y1*pixel_scale,
  684.       x*pixel_scale,y*pixel_scale+(fullscreen?40:0),(x2-x1+1)*pixel_scale,(y2-y1+1)*pixel_scale);
  685.  
  686. }
  687.  
  688. void put_image(image *im, int x, int y)
  689. {
  690.   put_part_image(mainwin,im,x,y,0,0,im->width()-1,im->height()-1);  
  691. }
  692.  
  693.  
  694.  
  695. void update_dirty_window(Window win, image *im, int xoff, int yoff)
  696. {
  697.  
  698.   int count;
  699.   dirty_rect *dr,*q;
  700.   image *Xim;
  701.   CHECK(im->special);  // make sure the image has the ablity to contain dirty areas
  702.   if (im->special->keep_dirt==0)
  703.     put_image(im,xoff,yoff);
  704.   else
  705.   {
  706.     count=im->special->dirties.number_nodes();
  707.     if (!count) return;  // if nothing to update, return
  708.     dr= (dirty_rect *) (im->special->dirties.first());
  709.     while (count>0)
  710.     {
  711.       put_part_image(win,im,xoff+dr->dx1,yoff+dr->dy1,dr->dx1,dr->dy1,dr->dx2,dr->dy2);     
  712. //      XDrawRectangle(display,mainwin,gc,xoff+dr->dx1,yoff+dr->dy1,
  713. //             xoff+dr->dx2-dr->dx1+1,yoff+dr->dy2-dr->dy1+1);
  714.       q=dr;
  715.       dr=(dirty_rect *) (dr->next());
  716.       im->special->dirties.unlink((linked_node *)q);
  717.       delete q;
  718.       count--;
  719.     }
  720.   }
  721. //  XFlush(display);
  722. }
  723.  
  724. void update_dirty(image *im, int xoff, int yoff)
  725. { update_dirty_window(mainwin,im,xoff,yoff); }
  726.  
  727. void palette::load()
  728. {
  729.   if (lastl)
  730.     delete lastl;
  731.   lastl=copy();
  732.  
  733.   {
  734.     int i;
  735.     if (get_vmode()!=XWINDOWS_2)
  736.     {
  737.       XColor colors[256];
  738.       for (i=0;i<ncolors;i++)
  739.       {
  740.           colors[i].flags=DoRed|DoBlue|DoGreen;
  741.                 colors[i].pixel=i;
  742.                 colors[i].red=red(i)<<8|0xff;
  743.                 colors[i].green=green(i)<<8|0xff;
  744.                 colors[i].blue=blue(i)<<8|0xff;
  745.       }
  746.             XStoreColors(display, XCMap, colors, 256);
  747.       XSetWindowColormap(display,mainwin,XCMap);
  748.     }
  749.     else lastl->black_white();
  750.     current_background=bg;
  751.   }
  752. }
  753.  
  754. struct hist_entry
  755. {
  756.   long total;
  757.   unsigned char org;
  758. } ;
  759.  
  760. static int histcompare(const void *i, const void *j)
  761.   if (((hist_entry *)i)->org==0) return -1;  // make sure the background gets allocated
  762.   else return(((hist_entry *)j)->total - ((hist_entry *)i)->total); 
  763. }
  764.  
  765.  
  766. void palette::load_nice()
  767. {
  768.   int i,fail,y,x,wd,j;
  769.   long closest_val,closest_pixel,k;
  770.   char *gotten;
  771.   image *im;
  772.   unsigned char *sl;
  773.   palette *Xpal;
  774.   hist_entry *histogram;
  775.   Colormap stdcm;
  776.   XColor color;
  777.  
  778.   if (get_vmode()!=XWINDOWS_2)  
  779.   {
  780.     filter f(ncolors);
  781.  
  782.     histogram=(hist_entry *)jmalloc(sizeof(hist_entry)*ncolors,"palette::histogram"); 
  783.     gotten=(char *)jmalloc(ncolors,"palette::gotten_colors");
  784.  
  785.     memset(gotten,0,ncolors);
  786.     for (i=0;i<ncolors;i++)
  787.     { histogram[i].total=0;
  788.       histogram[i].org=i;
  789.     }
  790.  
  791.     for (i=image_list.number_nodes(),im=(image *)image_list.first();i;i--,im=(image *)im->next()) 
  792.     { 
  793.       if (im!=screen)
  794.       { 
  795.         wd=im->width();
  796.         for (y=im->height();y;y--)
  797.         {
  798.           sl=im->scan_line(y-1);
  799.           for (x=0;x<wd;x++)
  800.             histogram[sl[x]].total++;
  801.         }
  802.       }
  803.     }
  804.     qsort(histogram,ncolors,sizeof(hist_entry),histcompare);
  805.     stdcm=XDefaultColormap(display,screen_num);
  806.     Xpal=NULL;
  807.     for (i=0,fail=0;i<ncolors;i++)
  808.     {
  809.       color.red=red(histogram[i].org)<<8; 
  810.       color.green=green(histogram[i].org)<<8; 
  811.       color.blue=blue(histogram[i].org)<<8; 
  812.  
  813.       if (XAllocColor(display,stdcm,&color))
  814.         f.set(histogram[i].org,color.pixel);
  815.       else  // if we couldn't allocate that color from X, find the closest.
  816.       {
  817.         if (!Xpal)
  818.         { Xpal=new palette(ncolors);
  819.           for (j=0;j<ncolors;j++)
  820.           {
  821.             color.pixel=j;
  822.             XQueryColor(display,stdcm,&color);
  823.             Xpal->set(j,color.red>>8,color.green>>8,color.blue>>8);
  824.           }
  825.         }
  826.         closest_val=0xfffffff;
  827.         for (j=0;j<ncolors;j++)
  828.         {
  829.           k=Xpal->red(j)*Xpal->red(j)+Xpal->green(j)*Xpal->green(j)+
  830.             Xpal->blue(j)*Xpal->blue(j);
  831.           if (k<closest_val)
  832.           { closest_val=k;
  833.             closest_pixel=j;
  834.           }
  835.         }
  836.         f.set(histogram[i].org,closest_pixel);
  837.       }
  838.     }
  839.     if (!Xpal)
  840.       Xpal=new palette(ncolors);
  841.     // store the color mapping we created back to the palette.
  842.     for (j=0;j<ncolors;j++)
  843.       Xpal->set(j,red(f.get_mapping(j)),green(f.get_mapping(j)),blue(f.get_mapping(j)));
  844.     for (j=0;j<ncolors;j++)
  845.       set(j,Xpal->red(j),Xpal->green(j),Xpal->blue(j));  
  846.     bg=f.get_mapping(bg);
  847.       
  848.     // now remap all the images to fit this colormap!
  849.     for (i=image_list.number_nodes(),im=(image *)image_list.first();i;i--,im=(image *)im->next()) 
  850.       f.apply(im);
  851.  
  852.     delete Xpal;
  853.     jfree(histogram);
  854.     jfree(gotten);
  855.   }
  856.   current_background=bg;
  857. }
  858.  
  859.